import logo from './logo.svg';
import './App.css';
import React,{createRef,createContext,useState,useEffect, useRef,useContext} from 'react';
import Child1 from './components/Child1';
import Child2 from './components/Child2';
import { render } from '@testing-library/react';
import Test1 from './components/Test1';
import Test2 from './components/Test2';
import Test3 from './components/Test3';
import Count from './components/Hooks-gaoji/Test01';
import Foo from './components/Hooks-gaoji/Test02'
import Test04,{Foo1} from './components/Hooks-gaoji/Test04';
// import {Foo2,Bar} from './components/Hooks-gaoji/Test05'
import { func } from 'prop-types';

// 1.创建Context对象
const {Provider,Consumer} = createContext()
const Context = createContext("")
const songs = [
  { id:1,name:'痴心绝对'
  },{
    id:2,name: '像我这样的人'
  },{
    id: 3,name: '南山南'
  }]


const styleObj = {
  // color: 'pink'
}
const flag = true

const showTitle = true

/**
 * # 组件状态 #
 *    * 注意：不要直接修改state中的值，必须通过setState方法进行修改
 * 
 */
// 类组件
class Counter extends React.Component {
  // 1.初始化状态(定义数据)
  state = {
    count: 0
  }
  // 2.定义修改数据的方法(ps:React的状态不可变，需要基于当前状态创建新值。)
  setCount = () => {
    this.setState({
      count: this.state.count + 1
    })
  }
  // 3.使用数据并绑定事件
  // 类组件必须提供render方法，render方法必须有返回值，表示该组件的UI结构
  render(){
    // 读取状态
    return <button onClick={this.setCount}>{this.state.count}</button>
  } 
}
/**
 * # 1.表单受控组件 #
 * 定义： input 框自己的状态被React组件控制
 * 实现步骤：
 *      1.在组件的state中声明一个组件的状态数据
 *      2.将状态数据设置为input标签的value属性的值
 *      3.为input 添加change事件，在事件处理程序中，通过事件对象e获取到当前文本框的值（即当前用户输入的值）
 *      4.调用setState方法，将文本框的值作为state状态的最新值
 */
class InputComponent extends React.Component {
  // 声明组件状态
  state = {
    messge: 'this is message'
  }
  // 声明事件回调函数
  changeHandler = (e) => {
    this.setState({
      messge: e.target.value
    })
  }
  render (){
    return (
      <div>
        {/* 绑定value，绑定事件 */}
        <input value={this.state.messge} onChange={this.changeHandler}></input>
      </div>
    )
  }
}
/**
 * # 2.非受控表单组件 #
 * 定义：通过手动操作dom的方式获取文本框的值，文本框的状态不受react组件的state中的状态控制，直接通过原生dom获取输入框的值。
 * 实现步骤：
 *      1.导入createRef函数
 *      2.调用createRef函数，创建一个ref对象，存储到名为msgRef的实例属性中
 *      3.为input 添加ref属性，值为msgRef
 *      4.在按钮的事件处理程序中，通过msgRef.current 即可拿到input对应的dom元素，而其中msgRef.current.value拿到的就是文本框的值
 * @returns 
 */
class InputComponent1 extends React.Component {
  // 使用createRef产生一个存放dom的对象容器，存放到msgRef的实例属性中
  msgRef = createRef()
  changeHandler1 = () => {
    console.log(this.msgRef.current.value);
  }
  render(){
    return (
      <div>
        {/* ref绑定，获取真实dom */}
        <input ref={this.msgRef} />
        <button onClick={this.changeHandler1}>click</button>
      </div>
    )
  }
}

// 函数组件
function HelloFn(){
  // 定义事件回调函数
  const clickHandler = (e) => {
    e.preventDefault()
    console.log('事件被触发了',e);
  }
  return (
    // 绑定事件
    <a href="http://www.baidu.com/" onClick={clickHandler}>百度</a>
  )
}

// 3. 消费数据
function ComC(){
  return (
    <Consumer>
      {value => <div>{value}</div>}
    </Consumer>
  )
}
function ComA(){
  return (
    <ComC />
  )
}
// 测试-清理副作用函数
function Test02Func (){
  const [flag,setFlag] = useState(true)
  return (
    <>
      <button onClick={()=>{setFlag(false)}}></button>
      {flag ? <Foo /> : null}
    </>
  )
}
// 测试-获取类组件实例
function Test04Class() {
    const h1Foo = useRef(null)
    useEffect(()=>{
      console.log(h1Foo);
    },[])
    return(
      <div>
        <Test04 ref={h1Foo}/>
      </div>
    )
}
// 测试-useContext 
function Test05useContext(){
  // 创建Context对象
  // const Context = createContext()
  // return (
    // // 顶层组件通过Provider 提供数据
    // <Context.Provider value={'this is name  父组件的数据'}>
    //   <Bar />
    // </Context.Provider>
  // )
} 
function Bar(){
  // 底层组件通过useContext 函数获取数据
  const name = useContext(Context)
  console.log(name,'获取的name');
  return <span>Bar1 {name}</span>
}

function Foo2() {
  return <div>Foo2 <Bar/></div>
}
// 2.提供数据
class App extends React.Component { 
    state = {
      msg: '父组件的值',
      message:'this is message'
    } 
    // 回调函数
    messageHandler = (newMsg) => {
      this.setState({msg:newMsg})
    }
    
  render(){
    return (
      <>
      {/* 顶层组件通过Provider 提供数据 */}
      <Context.Provider value={'this is name  父组件的数据'}>
        <Foo2 />
      </Context.Provider>
      {/* <Test05useContext /> */}
      <Test04Class />  
      <Foo1 />
      {/* <Test02Func /> */}
      <Count count={10}/>
      <Count count={20}/>
      <Test3 />
      <Test2 />
      <Test1 />
      <Provider value={this.state.message}>
        {/* 根组件 */}
        <div className="app">
          <ComA />
        </div>
      </Provider>
      {/* 非表单受控组件 */}
      <InputComponent1/>
      {/* 表单受控组件 */}
      <InputComponent/>
      <Counter/>
      <HelloFn/>
      {/* 这是一个幽灵节点，如果没有根节点，可以用这个代替（必须要有一个根节点）*/}
       {/* <div className="App"> */}
        {/* 条件渲染字符串 */}
        {flag ? 'react真有趣' : 'vue真有趣'}
        {/* 条件渲染标签/组件 */}
        {flag ? <span style={styleObj} className={ showTitle ? 'title' : ''}>this is not a div</span> : null}
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            Edit <code>src/App.js</code> and save to reload.
          </p>
          <a
            className="App-link"
            href="https://reactjs.org"
            target="_blank"
            rel="noopener noreferrer"
          >
            Learn React
          </a>
        </header>
      <ul>
        {songs.map((item,index) => { return(<li key={index}>{item.name}</li>)})}
      </ul>
      <Child1 msg={this.state.msg}/>
      <Child2 messageHandler={this.messageHandler}/>
      {/* </div> */}
      </>
    );
  }

}

export default App;
